#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/slab.h>




#define CNT_APD (2)

struct misc_apd_data {
	char name[16];
	int voltage;
	int temp_integer;
	int temp_decimal;
};


static ssize_t name_show(
    struct device *dev,
    struct device_attribute *attr,
    char *buf)
{
	struct misc_apd_data *pdata = (struct misc_batt_data *)dev->platform_data;

	return sprintf(buf, "%s\n", pdata->name);
}

static ssize_t apd_voltage_show(
    struct device *dev,
    struct device_attribute *attr,
    char *buf)
{
	struct misc_apd_data *pdata = (struct misc_apd_data *)dev->platform_data;

	return snprintf(buf, PAGE_SIZE, "%d\n", pdata->voltage);
}
static ssize_t apd_voltage_store(
    struct device *dev,
    struct device_attribute *attr,
    const char *buf, size_t count)
{
	struct misc_apd_data *pdata = (struct misc_apd_data *)dev->platform_data;
	char *after;
	int dat;
	int integer;
	int decimal;

	pdata->voltage = simple_strtoul(buf, &after, 10);

	// 电压转换成温度
	dat                 = pdata->voltage - 750;
	integer             = dat / 10;
	decimal             = (dat - integer * 10);
	pdata->temp_integer = integer + 25;
	pdata->temp_decimal = decimal;
	return count;
}


static ssize_t apd_temp_show(
    struct device *dev,
    struct device_attribute *attr,
    char *buf)
{
	struct misc_apd_data *pdata = (struct misc_apd_data *)dev->platform_data;
	return snprintf(buf, PAGE_SIZE, "%d.%d\n",
	                pdata->temp_integer,
	                abs(pdata->temp_decimal));
}


static DEVICE_ATTR(
    name, S_IRUGO, name_show, NULL);
static DEVICE_ATTR(
    voltage, S_IWUSR | S_IRUGO, apd_voltage_show, apd_voltage_store);
static DEVICE_ATTR(
    temp, S_IRUGO, apd_temp_show, NULL);
static struct miscdevice *pmisc;




int __init apd_init(void)
{
	int                   i;
	char                  name[16];
	struct device        *this_dev;
	struct miscdevice    *tpmisc;
	struct misc_apd_data *pdata, *tpdata;

	pmisc = kzalloc(sizeof(struct miscdevice) * CNT_APD, GFP_KERNEL);
	pdata = kzalloc(sizeof(struct misc_apd_data) * CNT_APD, GFP_KERNEL);

	tpdata = pdata, tpmisc = pmisc;
	for (i = 0; i < CNT_APD; i++) {
		snprintf(name, sizeof(name), "apd%d", i);
		tpmisc->name  = name;
		tpmisc->minor = MISC_DYNAMIC_MINOR;
		tpmisc->fops  = NULL;
		misc_register(tpmisc);

		this_dev                = tpmisc->this_device;
		this_dev->platform_data = tpdata;

		tpdata->voltage         = 750;  /* 默认750mV 大约20℃， */
		tpdata->temp_integer    = 25;   /* 默认温度 25.0 */
		tpdata->temp_decimal    = 0;
		strcpy(tpdata->name, name);

		device_create_file(this_dev, &dev_attr_name);
		device_create_file(this_dev, &dev_attr_voltage);
		device_create_file(this_dev, &dev_attr_temp);
		tpmisc++, tpdata++;
	}
	return 0;
}

void __exit apd_exit(void)
{
	int i;
	struct miscdevice *tpmisc;

	if (pmisc) {
		tpmisc = pmisc;
		for (i = 0; i < CNT_APD; i++) {
			misc_deregister(tpmisc);
			tpmisc++;
		}
		kfree(pmisc);
	}
}


#if 0
module_init(apd_init);
module_exit(apd_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("glink devices user space export");
#endif
